#ifndef __INC_ALU
#define __INC_ALU

/*
 * Forward declare ALU because it's circularly referenced by other classes.
 */
typedef struct alu2 Alu;

#include "register.h"
#include "../cpu/cpu.h"

/*
 * An ALU type.
 */
struct alu2
{
	/*
	 * The first operand to use for ALU operations.
	 */
	Register operand_a;
	
	/*
	 * The second operand to use for ALU operations. This register is unused for unary operations
	 * like NEG and NOT.
	 */
	Register operand_b;
	
	/*
	 * The result of the last ALU operation. This value is undefined if no operations have occurred.
	 */
	Register result_r;
	
	/*
	 * A pointer to the processor object, used to set the PSR after an operation.
	 */
	Cpu *cpu;
};

/*
 * Alu *new_alu(Cpu *cpu);
 * Constructs a new ALU and returns a pointer to it.
 * cpu: a pointer to the processor object, used to set the PSR after an operation.
 */
Alu *new_alu(Cpu *cpu);

/*
 * void alu_set_operand_a(Alu *alu, unsigned short value);
 * Sets the contents of the ALU's operand A register.
 * alu: a pointer to the ALU
 * value: the value to set
 */
void alu_set_operand_a(Alu *alu, unsigned short value);

/*
 * void alu_set_operand_b(Alu *alu, unsigned short value);
 * Sets the contents of the ALU's operand B register.
 * alu: a pointer to the ALU
 * value: the value to set
 */
void alu_set_operand_b(Alu *alu, unsigned short value);

/*
 * unsigned short alu_get_result_r(Alu *alu);
 * Gets the value of the ALU's result register.
 * alu: a pointer to the ALU
 */
unsigned short alu_get_result_r(Alu *alu);

/*
 * void alu_neg(Alu *alu);
 * Performs a negation operation with the ALU's operand A and stores the result in the result
 * register.
 * alu: a pointer to the ALU
 */
void alu_neg(Alu *alu);

/*
 * void alu_add(Alu *alu);
 * Performs an addition operation with the ALU's operands A and B and stores the result in the
 * result register.
 * alu: a pointer to the ALU
 */
void alu_add(Alu *alu);

/*
 * void alu_sub(Alu *alu);
 * Performs a subtraction operation with the ALU's operands A and B and stores the result in the
 * result register.
 * alu: a pointer to the ALU
 */
void alu_sub(Alu *alu);

/*
 * void alu_and(Alu *alu);
 * Performs a logical AND operation with the ALU's operands A and B and stores the result in the
 * result register.
 * alu: a pointer to the ALU
 */
void alu_and(Alu *alu);

/*
 * void alu_or(Alu *alu);
 * Performs a logical OR operation with the ALU's operands A and B and stores the result in the
 * result register.
 * alu: a pointer to the ALU
 */
void alu_or(Alu *alu);

/*
 * void alu_not(Alu *alu);
 * Performs a logical NOT operation with the ALU's operand A and stores the result in the result
 * register.
 * alu: a pointer to the ALU
 */
void alu_not(Alu *alu);

/*
 * void delete_alu(Alu *alu);
 * Frees the memory associated with this ALU.
 * alu: a pointer to the ALU to delete
 */
void delete_alu(Alu *alu);

#endif
